package blackberry.util.image;

import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Field;

public class DjImageCalculator{
	
	public static final int NONE = 0;
	
	private DjImageCalculator() {
	}
	
	/**
	 * Image를 새로운 Background에 옮길겼을때의 Height, Width 값을 반환한다
	 * 기존의 Bitmap에 Fit과 Fill 기능이 있지만 값을 직접 알고 싶을때 사용한다.
	 */
	public static int[] fillIntoDisplay(double imageWidth, double imageHeight) {
		
		return engineOfFitAndFill(
				imageWidth, imageHeight, 
				Display.getWidth(), Display.getHeight(), 
				true);
	}
	public static int[] fillIntoNewBackground(double imageWidth, double imageHeight,
			int newBackgroundWidth, int newBackgroundHeight) {
		
		return engineOfFitAndFill(
				imageWidth, imageHeight, 
				newBackgroundWidth, newBackgroundHeight, 
				true);
	}
	
	public static int[] fitIntoDisplay(double imageWidth, double imageHeight) {
	
		return engineOfFitAndFill(
				imageWidth, imageHeight, 
				Display.getWidth(), Display.getHeight(), 
				false);
	}
	public static int[] fitIntoNewBackground(double imageWidth, double imageHeight,
			int newBackgroundWidth, int newBackgroundHeight) {
		
		return engineOfFitAndFill(
				imageWidth, imageHeight, 
				newBackgroundWidth, newBackgroundHeight, 
				false);
	}
	
	private static int[] engineOfFitAndFill(double imageWidth, double imageHeight, 
			int backgroundWidth, int backgroundHeight, boolean fill) {
		
		double ratio = getRatio(imageWidth, imageHeight);
		double extracedNewHeight = extractHeightFromWidth(ratio, backgroundWidth);
		
		//newBackground 과 oldBackground들의 가로세로 비율이 같을때
		if (extracedNewHeight == backgroundHeight) {
		
			return new int[] {backgroundWidth, backgroundHeight};
			
		//기준을 newBackgroundWith로 잡고 old들의 비율을 적용해서 계산했을시 
		//계산한 Height값이 더 큰상태로 진행하면 fill / 더 작은상태로 진행하면 fit
		} else if (compareExtractedNewHeightAndNewHeight(backgroundHeight, extracedNewHeight, fill)) {
			
			return new int[] { backgroundWidth, extractHeightFromWidth(ratio, backgroundWidth)};
			
		//기준을 newBackgroundHeight로 잡고 oldBackground들의 비율을 적용했을시 
		//newBackground의 가로가 남을때
		} else {
			
			return new int[] { extractWidthFromHeight(ratio, backgroundHeight), backgroundHeight};
		} 
	}
	private static boolean compareExtractedNewHeightAndNewHeight(int newHeight,
			double extractedHeight, boolean fill) {
		
		return (fill) ? newHeight < extractedHeight
				: newHeight > extractedHeight;
	}
	
	
	/**
	 * 비율은 그대로 유지하며 이미지 크기를 변경하려고 할때 사용한다.
	 * newWidth 나 newHeight 둘중에 한가지 정보만 입력하면 나머지를 계산해준다.
	 */
	public static int extractHeightFromWidth(double oldWidth, double oldHeight, int newWidth){
		return extractHeightFromWidth(getRatio(oldWidth, oldHeight), newWidth);
	}
	private static int extractHeightFromWidth(double ratio , int newWidth){
		return (int) (newWidth / ratio);
	}
	
	public static int extractWidthFromHeight(double oldWidth, double oldHeight, int newHeight){
		return extractWidthFromHeight(getRatio(oldWidth, oldHeight), newHeight);
	}
	private static int extractWidthFromHeight(double ratio, int newHeight){
		return (int) (newHeight * ratio);
	}
	
	private static double getRatio(double oldWidth, double oldHeight) {
		return oldWidth / oldHeight;
	}
	
	
	/**
	 * 포토샵에서 작업한 그림을 같은 비율로 옮길때 사용한다
	 * Image, OldBackground, NewBackground 이렇게 3가지 정보가 필요하다
	 */
	public static int imageXIntoNewBackground(int imageX, int oldBackgroundWidth, int oldBackgroundHeight,
			int newBackgroundWidth, int newBackgroundHeight) {
		return newBackgroundWidth * imageX / oldBackgroundWidth;
	}
	
	public static int imageXIntoDisplay(int imageX, int oldBackgroundWidth) {
		return imageXIntoNewBackground(imageX, oldBackgroundWidth, Display.getWidth());
	}
	public static int imageXIntoNewBackground(int imageX, int oldBackgroundWidth, int newBackgroundWidth) {
		return newBackgroundWidth * imageX / oldBackgroundWidth;
	}
	
	public static int imageYIntoDisplay(int imageY, int oldBackgroundHeight) {
		return imageYIntoNewBackground(imageY, oldBackgroundHeight, Display.getHeight());
	}
	public static int imageYIntoNewBackground(int imageY, int oldBackgroundHeight, int newBackgroundHeight) {
		return newBackgroundHeight * imageY / oldBackgroundHeight;
	}
	
	public static int imageWidthIntoDisplay(int imageWidth, int oldBackgroundWidth){
		return imageWidthIntoNewBackground(imageWidth, oldBackgroundWidth, Display.getWidth());
	}
	public static int imageWidthIntoNewBackground(int imageWidth, int oldBackgroundWidth, int newBackgroundWidth) {
		return newBackgroundWidth * imageWidth / oldBackgroundWidth;
	}
	
	public static int imageHeightIntoDisplay(int imageHeight, int oldBackgroundHeight){
		return imageHeightIntoNewBackground(imageHeight, oldBackgroundHeight, Display.getHeight());
	}
	public static int imageHeightIntoNewBackground(int imageHeight, int oldBackgroundHeight, int newBackgroundHeight) {
		return newBackgroundHeight * imageHeight / oldBackgroundHeight;
	}
	
	
	/**
	 * Fill처리를 해서 이미지의 크기가 달라졌을경우, 또는 보이는 화면보다 이미지의 크기가 커서
	 * 잘라내야 할 경우 새롭게 다듬어진 X, Y 좌표를 반환한다
	 */
	public static int refineYIntoDisplay(int oldY, int oldBackgroundWidth, int oldBackgroundHeight,
			long direction) {
		return refineYIntoNewBackground(oldY, oldBackgroundWidth, oldBackgroundHeight, 
				Display.getWidth(), Display.getHeight(), direction);
	}
	public static int refineYIntoNewBackground(int oldY, int oldBackgroundWidth, int oldBackgroundHeight,
			int newBackgroundWidth, int newBackgroundHeight, long direction){
		
		int filledHieght = DjImageCalculator.fillIntoNewBackground(
				oldBackgroundWidth, 
				oldBackgroundHeight,
				newBackgroundWidth,
				newBackgroundHeight)[1];

		int YIntoFilledHeight = DjImageCalculator.imageYIntoNewBackground(
				oldY, 
				oldBackgroundHeight, 
				filledHieght);

		if (direction == Field.FIELD_VCENTER) {
		
			return YIntoFilledHeight - ((filledHieght - newBackgroundHeight) / 2);
			
		} else if (direction == Field.FIELD_TOP) {
			
			return YIntoFilledHeight - (filledHieght - newBackgroundHeight);
			
		} else {
			
			return YIntoFilledHeight;
		}
	}
	
	
	public static int refineXIntoDisplay(int oldX, int oldBackgroundWidth, int oldBackgroundHeight, 
			long direction) {
		return refineXIntoNewBackground(oldX, oldBackgroundWidth, oldBackgroundHeight, 
				Display.getWidth(), Display.getHeight(), direction);
		
	}
	public static int refineXIntoNewBackground(int oldX, int oldBackgroundWidth, int oldBackgroundHeight, 
			int newBackgroundWidth, int newBackgroundHeight, long direction){
		
			
		int filledWidth = DjImageCalculator.fillIntoNewBackground(
				oldBackgroundWidth, 
				oldBackgroundHeight, 
				newBackgroundWidth, 
				newBackgroundHeight)[0];

		
		int XIntoFilledWidth = DjImageCalculator.imageXIntoNewBackground(
				oldX, 
				oldBackgroundWidth, 
				filledWidth);
		
		
		if (direction == Field.FIELD_HCENTER) {
			
			return XIntoFilledWidth - ((filledWidth - newBackgroundWidth) / 2);
			
		} else if (direction == Field.FIELD_LEFT) {
			
			return XIntoFilledWidth - (filledWidth - newBackgroundWidth);
			
		} else {
			
			return XIntoFilledWidth;
		}
	}
}